package ru.nsu.fit.iconveyor.conveyor.utils.zip;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Zip {
    public static void zip(String outputZipFile, String sourceFolder) throws Exception {
        List<String> fileList = new ArrayList<String>();
        generateFileList(new File(sourceFolder), sourceFolder, fileList);
        zipIt(outputZipFile, sourceFolder, fileList);
    }

    public static void zipWithoutRootFolder(String outputZipFile, String sourceFolder) throws Exception {
        List<String> fileList = new ArrayList<String>();
        generateFileList(new File(sourceFolder), sourceFolder, fileList);
        fileList.remove(sourceFolder);
        zipIt(outputZipFile, sourceFolder, fileList);
    }

    private static void zipIt(String outputZipFile, String sourceFolder, List<String> fileList) throws Exception {

        byte[] buffer = new byte[1024];

        try {

            FileOutputStream fos = new FileOutputStream(outputZipFile);
            ZipOutputStream zos = new ZipOutputStream(fos);

            for (String file : fileList) {
                ZipEntry ze = new ZipEntry(file);
                zos.putNextEntry(ze);

                FileInputStream in = new FileInputStream(sourceFolder
                        + File.separator + file);

                int len;
                while ((len = in.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }

                in.close();
            }

            zos.closeEntry();
            // remember close it
            zos.close();
        } catch (IOException ex) {
            throw ex;
        }
    }

    /**
     * Traverse a directory and get all files, and add the file into fileList
     *
     * @param node file or directory
     */
    private static void generateFileList(File node, String sourceFolder, List<String> fileList) {
        // add file only
        if (node.isFile()) {
            fileList.add(generateZipEntry(sourceFolder, node.getAbsolutePath()));
        }

        if (node.isDirectory()) {
            String[] subNote = node.list();
            for (String filename : subNote) {
                generateFileList(new File(node, filename), sourceFolder, fileList);
            }
        }

    }

    private static String generateZipEntry(String sourceFolder, String file) {
        return file.substring(sourceFolder.length() + 1, file.length());
    }
}
